/************************************************************************
  * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
  * @file     sd_update.c
  * @author   UartTFT Application Team
  * @version  V0.0.1
  * @date     2023-01-01
  * @brief    
 *************************************************************************/

#include "sd_update.h"
#include "ff.h"
#include "diskio.h"
#include "w25n01.h"
#include "w25qxx.h"
#include "pit.h"
#include "function.h"
#include "bsp.h"
#include "qspi.h"
#include "reset_drv.h"
#include "function_drv.h"
#include "delay.h"

uint8_t SD_ud_flag = 0;

uint8_t Sd_To_Flash(void)
{
	BYTE buf[2048];
	FATFS fs;
	FIL fsrc;
	FRESULT res;
	UINT br;
	uint8_t num = 0, flag = 0;
	uint16_t page = 0;
	uint32_t k, addr = 0, size = 0, Block_Num;

	for (uint8_t i = 0; i < 5; i++)
	{
		DelayMS(10);
		if (SD_detection())
		{
//			printf("SD_detection  OUT  \r\n ");
			return 1;
		}
	}
	//	FF_Update_Flag = 2;
	LT_UsartTimeDisable(); // close pit1

	LT268_TFT_FillColor(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, Blue2);
	LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"Automatically update flash after 3 s");
	DelayMS(1000);
	LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"Automatically update flash after 2 s");
	DelayMS(1000);
	LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"Automatically update flash after 1 s");
	DelayMS(500);

	//	PIT1_Init_SD();

	if (SD_detection())
	{
//		printf("SD_detection  OUT  \r\n ");
		Set_POR_Reset();
	}

	// erase
	res = f_mount(&fs, "0:", 1);
	if (res == 0)
		res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
	if (res == 0)
	{
		size = f_size(&fsrc);

		SD_SPI_close(); 
		LT268_TFT_FillColor(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, Blue2);
		LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing");

		SSI1_STD_Init(SSI1);
		if (Flash_Type != 2)
		{
			Block_Num = size / NorBlockSize;

			for (k = 0; k <= Block_Num; k++)
			{
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing.  ");
				W25QXX_BlockErase64KB(k * NorBlockSize);
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing...");
			}
		}
		else
		{
			Block_Num = size / NandBlockSize;
			for (k = 0; k <= Block_Num; k++)
			{
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing.  ");
				LT_W25N01GV_BlockErase128KB(k * NandBlockSize);
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing...");
			}
		}

		LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 - 24, 24, 0, Red, Blue2, (uint8_t *)"flash erasing ok!");
		LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  0%");
	}

	// SD_IN
	if (SD_detection())
	{
		Set_POR_Reset();
	}

	// Burn
	if (res == 0)
	{
		res = f_mount(&fs, "0:", 1);
		res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
	}

	if (res == 0)
	{
		do
		{
			num = addr * 100 / size;

			if (20 <= num && num < 40 && flag == 0)
			{
				flag = 1;
				f_close(&fsrc);

				SD_SPI_close(); 
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  20%");

				f_mount(&fs, "0:", 1);
				res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
				f_lseek(&fsrc, addr);
			}
			else if (40 <= num && num < 60 && flag == 1)
			{
				flag = 2;
				f_close(&fsrc);

				SD_SPI_close(); 
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  40%");

				f_mount(&fs, "0:", 1);
				res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
				f_lseek(&fsrc, addr);
			}
			else if (60 <= num && num < 80 && flag == 2)
			{
				flag = 3;
				f_close(&fsrc);

				SD_SPI_close(); 
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  60%");

				f_mount(&fs, "0:", 1);
				res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
				f_lseek(&fsrc, addr);
			}
			else if (80 <= num && num < 100 && flag == 3)
			{
				flag = 4;
				f_close(&fsrc);

				SD_SPI_close(); 
				LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  80%");

				f_mount(&fs, "0:", 1);
				res = f_open(&fsrc, "0:/UartTFT_Flash/UartTFT-II_Flash.bin", FA_OPEN_EXISTING | FA_READ);
				f_lseek(&fsrc, addr);
			}

			res = f_read(&fsrc, buf, 2048, &br);
			if (res || (br == 0))
			{
				f_close(&fsrc);
				break;
			}
			if (Flash_Type != 2)
			{
				W25QXX_STD_Write_NoCheck(buf, addr, br);
			}
			else
			{
				// LT_W25N01GV_Write_Page(buf,page,2048);
				LT_W25N01GV_STD_Write_Page_DMA(buf, page, 0, 2048);
				page++;
			}
			addr += br; // Address accumulation

		} while (!SD_detection()); // By detecting the high and low level of the wakeup pin. If an SD card is inserted (0)

		if (flag == 4 && br == 0)
		{
			SD_SPI_close(); 
			LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2, 24, 0, Red, Blue2, (uint8_t *)"updating  100%");
			LT268_TFT_ShowAscll(10, LCD_YSIZE_TFT / 2 + 30, 24, 0, Red, Blue2, (uint8_t *)"please remove the SD card");
			DelayMS(1000);
		}
	}

	//	sd_flag = 0;
	Set_POR_Reset(); //MCU reset

	return 0;
}
